package com.wteam.dragon.shop.service.impl;

import cn.hutool.core.lang.Dict;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wteam.dragon.shop.mapper.*;
import com.wteam.dragon.shop.pojo.bean.*;
import com.wteam.dragon.shop.pojo.dto.CouponDto;
import com.wteam.dragon.shop.service.CouponService;
import com.wteam.dragon.system.basebean.bean.ResultMessage;
import com.wteam.dragon.system.exception.BadRequestException;
import com.wteam.dragon.system.util.UserUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * @Author 陈晓辉
 * @Date 2021/3/24 20:42
 */
@Service
@RequiredArgsConstructor
public class CouponServiceImpl implements CouponService {
    private final CouponMapper couponMapper;
    private final CouponProductMapper couponProductMapper;
    private final CouponProductSortMapper couponProductSortMapper;
    private final ProductSortMapper productSortMapper;
    private final ProductMapper productMapper;
    private final CouponHistoryMapper couponHistoryMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage addCoupon(Coupon coupon, List<Long> productSortIds, List<Long> productIds) {
        couponMapper.insert(coupon);
        dealCoupon(coupon, productSortIds, productIds);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setMessage("添加成功");
        return resultMessage;
    }

    /**
     * 普通处理优惠卷和商品类型以及商品之间的关系
     * 用于新增优惠卷的时候
     */
    private void dealCoupon(Coupon coupon, List<Long> productSortIds, List<Long> productIds) {
        //指定分类
        if (coupon.getUseType().equals(1)) {
            if (productSortIds.size() == 0) {
                throw new BadRequestException("请指定商品分类");
            }
            productSortIds.forEach(productSortId -> {
                CouponProductSort couponProductSort = new CouponProductSort();
                couponProductSort.setCouponId(coupon.getId());
                couponProductSort.setProductSortId(productSortId);
                couponProductSortMapper.insert(couponProductSort);
            });
            //指定商品
        } else if (coupon.getUseType().equals(2)) {
            if (productIds.size() == 0) {
                throw new BadRequestException("请指定商品");
            }
            productIds.forEach(productId -> {
                CouponProduct couponProduct = new CouponProduct();
                couponProduct.setCouponId(coupon.getId());
                couponProduct.setProductId(productId);
                couponProductMapper.insert(couponProduct);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage delCoupon(Long id) {
        couponMapper.deleteById(id);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setMessage("删除成功");
        return resultMessage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage editCoupon(Coupon coupon, List<Long> productSortIds, List<Long> productIds) {
        Coupon old = couponMapper.selectById(coupon.getId());
        //新优惠卷与旧优惠卷的使用状态有更改
        if (!old.getType().equals(coupon.getType())) {
            //删除旧优惠卷关联的商品类型或者商品
            if (!old.getUseType().equals(0)) {
                if (old.getUseType().equals(1)) {
                    QueryWrapper<CouponProductSort> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .eq(CouponProductSort::getCouponId, coupon.getId());
                    couponProductSortMapper.delete(queryWrapper);
                } else if (old.getUseType().equals(2)) {
                    QueryWrapper<CouponProduct> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .eq(CouponProduct::getCouponId, coupon.getId());
                    couponProductMapper.delete(queryWrapper);
                }
            }
            dealCoupon(coupon, productSortIds, productIds);
        } else {
            if (!coupon.getType().equals(0)) {
                if (coupon.getUseType().equals(1)) {
                    QueryWrapper<CouponProductSort> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .select(CouponProductSort::getProductSortId)
                            .eq(CouponProductSort::getCouponId, coupon.getId());
                    List<Long> oldIds = couponProductSortMapper.selectList(queryWrapper).stream().map(CouponProductSort::getProductSortId).collect(Collectors.toList());
                    //求交集
                    List<Long> in = oldIds.stream().filter(productSortIds::contains).collect(Collectors.toList());
                    //获得删除的部分
                    oldIds.removeAll(in);
                    //获得添加的部分
                    productSortIds.removeAll(in);
                    //进行添加和删除
                    couponProductSortMapper.deleteBatchIds(oldIds);
                    productSortIds.forEach(productSortId -> {
                        CouponProductSort couponProductSort = new CouponProductSort();
                        couponProductSort.setCouponId(coupon.getId());
                        couponProductSort.setProductSortId(productSortId);
                        couponProductSortMapper.insert(couponProductSort);
                    });
                } else if (coupon.getUseType().equals(2)) {
                    QueryWrapper<CouponProduct> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .select(CouponProduct::getProductId)
                            .eq(CouponProduct::getCouponId, coupon.getId());
                    List<Long> oldIds = couponProductMapper.selectList(queryWrapper).stream().map(CouponProduct::getProductId).collect(Collectors.toList());
                    //求交集
                    List<Long> in = oldIds.stream().filter(productIds::contains).collect(Collectors.toList());
                    //获得删除的部分
                    oldIds.removeAll(in);
                    //获得添加的部分
                    productIds.removeAll(in);
                    //进行添加和删除
                    couponProductMapper.deleteBatchIds(oldIds);
                    productIds.forEach(productId -> {
                        CouponProduct couponProduct = new CouponProduct();
                        couponProduct.setCouponId(coupon.getId());
                        couponProduct.setProductId(productId);
                        couponProductMapper.insert(couponProduct);
                    });
                }
            }
        }
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setMessage("编辑成功");
        return resultMessage;
    }

    @Override
    public ResultMessage pageCoupon(Page<Coupon> page, String name, Integer type) {
        QueryWrapper<Coupon> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .like(name != null, Coupon::getName, name)
                .eq(type != null, Coupon::getType, type);
        Page<Coupon> couponPage = couponMapper.selectPage(page, queryWrapper);
        Dict resultMap = Dict.create()
                .set("message", "请求成功")
                .set("couponPage", couponPage);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setResultParam(resultMap);
        return resultMessage;
    }

    @Override
    public ResultMessage getCoupon(Long id) {
        Coupon coupon = couponMapper.selectById(id);
        //将coupon转成couponDto
        CouponDto couponDto = new CouponDto();
        couponDto.setCoupon(coupon);
        if (coupon.getUseType().equals(1)) {
            QueryWrapper<CouponProductSort> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .select(CouponProductSort::getProductSortId)
                    .eq(CouponProductSort::getCouponId, coupon.getId());
            List<ProductSort> productSortList = couponProductSortMapper.selectList(queryWrapper).stream().map(couponProductSort -> productSortMapper.selectById(couponProductSort.getProductSortId())).collect(Collectors.toList());
            couponDto.setProductSortList(productSortList);
        } else if (coupon.getUseType().equals(2)) {
            QueryWrapper<CouponProduct> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .select(CouponProduct::getProductId)
                    .eq(CouponProduct::getCouponId, coupon.getId());
            List<Product> productList = couponProductMapper.selectList(queryWrapper).stream().map(couponProduct -> productMapper.selectById(couponProduct.getProductId())).collect(Collectors.toList());
            couponDto.setProductList(productList);
        }
        Dict resultMap = Dict.create()
                .set("message", "请求成功")
                .set("couponDto", couponDto);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setResultParam(resultMap);
        return resultMessage;
    }


    @Override
    public ResultMessage receiveCoupon(Long id) {
        Coupon coupon = couponMapper.selectById(id);
        Date date = new Date(System.currentTimeMillis());
        if (coupon.getStartTime().compareTo(date) > 0) {
            throw new BadRequestException("还没到领取时间");
        }
        if (coupon.getEndTime().compareTo(date) < 0) {
            throw new BadRequestException("已经超过了领取时间");
        }
        if (coupon.getCount().compareTo(0) <= 0) {
            throw new BadRequestException("该优惠卷已经被领取完了");
        }
        //判断是否达到该用户领取上限
        QueryWrapper<CouponHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(CouponHistory::getCreateId, UserUtil.getCurrentUserId())
                .eq(CouponHistory::getCouponId, id);
        Integer count = couponHistoryMapper.selectCount(queryWrapper);
        if (coupon.getPerLimit().compareTo(count) <= 0) {
            throw new BadRequestException("该优惠卷已经达到了领取上限");
        }
        //添加历史优惠卷
        CouponHistory couponHistory = new CouponHistory();
        couponHistory.setCouponId(id);
        couponHistory.setGetWay(1);
        couponHistory.setCouponCode(generateCouponCode(UserUtil.getCurrentUserId()));
        couponHistoryMapper.insert(couponHistory);
        //修改优惠卷数量和领取数量
        coupon.setCount(coupon.getCount() - 1);
        coupon.setReceiveCount(coupon.getReceiveCount() + 1);
        couponMapper.updateById(coupon);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setMessage("领取成功");
        return resultMessage;
    }

    /**
     * 16位优惠码生成：时间戳后8位+4位随机数+用户id后4位
     */
    private String generateCouponCode(Long memberId) {
        StringBuilder sb = new StringBuilder();
        long currentTimeMillis = System.currentTimeMillis();
        String timeMillisStr = Long.toString(currentTimeMillis);
        sb.append(timeMillisStr.substring(timeMillisStr.length() - 8));
        for (int i = 0; i < 4; i++) {
            sb.append(new Random().nextInt(10));
        }
        String memberIdStr = memberId.toString();
        if (memberIdStr.length() <= 4) {
            sb.append(String.format("%04d", memberId));
        } else {
            sb.append(memberIdStr.substring(memberIdStr.length() - 4));
        }
        return sb.toString();
    }

    @Override
    public ResultMessage pageCouponHistory(Page<CouponHistory> page, Integer useStatus) {
        QueryWrapper<CouponHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(useStatus != null, CouponHistory::getUseStatus, useStatus)
                .eq(CouponHistory::getCreateId, UserUtil.getCurrentUserId());
        Page<CouponHistory> couponHistoryPage = couponHistoryMapper.selectPage(page, queryWrapper);
        Dict resultMap = Dict.create()
                .set("message", "请求成功")
                .set("couponHistoryPage", couponHistoryPage);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setStatus(HttpStatus.OK.value());
        resultMessage.setResultParam(resultMap);
        return resultMessage;
    }
}
